/**
 *  @file
 *  @brief   枚举类DOFDirections定义，标识自由度方向
 *  @author  wanghuan
 *  @date    2024.02.29
 *  @version  v1.0
 *  @par Copyright(c):  ShenGong  Simulation corporation
 */

#pragma once
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>

#include "Utility/Logging/SGLogger.h"
#include "DataStructure/Common/DataStructureExport.h"
#include "DataStructure/Common/DataStructureNamespace.h"
#include "DataStructure/Common/Integer.h"

SG_DATASTRUCTURE_FEM_NAMESPACE_OPEN

/** \enum DOFDirections
 *  自由度方向定义
 */
enum DOFDirections
{
    DOF_Unknow = -1,  ///< 未定义
    DOF_Ux     = 0,   ///< x方向线自由度
    DOF_Uy     = 1,   ///< y方向线自由度
    DOF_Uz     = 2,   ///< z方向线自由度
    DOF_Rotx   = 3,   ///< 绕x轴旋转自由度方向
    DOF_Roty   = 4,   ///< 绕y轴旋转自由度方向
    DOF_Rotz   = 5,   ///< 绕z轴旋转自由度方向
};

using DofSet = std::vector<DOFDirections>;

static const std::vector<std::string> TRAN_DIRECTION_STR{ "Ux", "Uy", "Uz" };
static const std::vector<std::string> ROT_DIRECTION_STR{ "Rotx", "Roty", "Rotz" };

/** @brief 获取节点的全部自由度*/
inline DofSet getAllNodeDofs ()
{
    return { DOFDirections::DOF_Ux,   DOFDirections::DOF_Uy,   DOFDirections::DOF_Uz,
             DOFDirections::DOF_Rotx, DOFDirections::DOF_Roty, DOFDirections::DOF_Rotz };
}

/** @brief 某个自由度是否包含在自由度集合中 */
inline bool includeThisDOF (const SG::DataStructure::FEM::DofSet& dofs, std::size_t direction)
{
    bool result = false;
    for (const auto dof : dofs)
    {
        if (static_cast<std::size_t> (dof) == direction)
        {
            result = true;
            break;
        }
    }

    return result;
}

inline int DofSet2Int (const DofSet& v_DofSet)
{
    int         result = 0;
    std::size_t vLen   = v_DofSet.size ();
    for (std::size_t i = 0; i < vLen; i++)
    {
        switch (v_DofSet[i])
        {
        case DOFDirections::DOF_Ux:
            result += 1 * static_cast<int> (pow (10, vLen - i - 1));
            break;
        case DOFDirections::DOF_Uy:
            result += 2 * static_cast<int> (pow (10, vLen - i - 1));
            break;
        case DOFDirections::DOF_Uz:
            result += 3 * static_cast<int> (pow (10, vLen - i - 1));
            break;
        case DOFDirections::DOF_Rotx:
            result += 4 * static_cast<int> (pow (10, vLen - i - 1));
            break;
        case DOFDirections::DOF_Roty:
            result += 5 * static_cast<int> (pow (10, vLen - i - 1));
            break;
        case DOFDirections::DOF_Rotz:
            result += 6 * static_cast<int> (pow (10, vLen - i - 1));
            break;
        default:
            break;
        }
    }
    return result;
};

/**
 * @brief    计算数值和direction 的映射
 * 
 * @param    val       传入值为 1-6
 * @return   
 * @author   wanghuan
 * @date     2025.11.03
 */
inline DOFDirections GetOneDirection (int val)
{
    if (val < 1 || val > 6)
    {
        SGFatal << "invaild input value";
    }
    return DOFDirections(val- 1);
}

inline DofSet Int2VDofSet (int int_DofSet)
{
    DofSet vDof;
    while (int_DofSet > 0)
    {
        vDof.push_back (static_cast<DOFDirections> (int_DofSet % 10 - 1));  // 提取最后一位数字
        int_DofSet /= 10;                                                   // 去掉最后一位数字
    }

    std::reverse (vDof.begin (), vDof.end ());
    return vDof;
};

SG_DATASTRUCTURE_FEM_NAMESPACE_CLOSE